#!/usr/bin/env python
# -*- coding: utf8 -*-

import cairo
import sys

VERSION = "0.2.2"

class Hexagone(object):
    '''
    Gère les hexagones
    '''
    DESERT_TXT = "desert"
    BOIS_TXT = "bois"
    BLE_TXT = "ble"
    ARGILE_TXT = "argile"
    MINERAI_TXT = "minerai"
    MOUTON_TXT = "mouton"
    MER_TXT = "mer"
    PROBA_TAB = {0:0,2:1,3:2,4:3,5:4,6:5,7:6,8:5,9:4,10:3,11:2,12:1}
    def __init__(self,x,y,matiere,valeur):
        self.x = x
        self.y = y
        self.matiere = matiere
        self.valeur = valeur
        self.noeuds = [0,0,0,0,0,0] #aiguille d'une montre noeud1 = en haut à gauche
    def printClass(self):
        print "%s en (%s,%s) avec la valeur %s et les noeuds {%d,%d,%d,%d,%d,%d}" % (self.matiere,self.x,self.y,self.valeur,self.noeuds[0],self.noeuds[1],self.noeuds[2],self.noeuds[3],self.noeuds[4],self.noeuds[5])

class ListeHexagone(object):
    '''
    Gère la liste des hexagones
    '''
    def __init__(self):
        self.liste = {}
    
    def ajouteHexagone(self,hex):
        if self.liste.has_key(hex.x):
            self.liste[hex.x][hex.y]=hex
        else:
            self.liste[hex.x] = {hex.y:hex}
    
    def printClass(self):
        for ligne,colonne in self.liste.iteritems():
            print "-- ligne (%d) --" % ligne
            for ligneBis,colonneBis in colonne.iteritems():
                colonneBis.printClass()
    def calculerProbaNoeud(self):
        '''
        Calcule les probas par noeud
        '''
        for ligne,colonne in self.liste.iteritems():
            for ligneBis,colonneBis in colonne.iteritems():
                hex = colonneBis
                for numNoeud in range (0,6):
                    voisins = self.getVoisins(hex,numNoeud)
                    if voisins[0] != None:
                        valeur1 = voisins[0].valeur
                    else:
                        valeur1 = 0
                    if voisins[1] != None:
                        valeur2 = voisins[1].valeur
                    else:
                        valeur2 = 0
                    hex.noeuds[numNoeud] = (Hexagone.PROBA_TAB[hex.valeur] + Hexagone.PROBA_TAB[valeur1] + Hexagone.PROBA_TAB[valeur2])/36.0*100        
                        
    def getHexagone(self,x,y):
        #print "je cherche l'hexagone %d %d" % (x,y)
        if self.liste.has_key(x):
            listex = self.liste[x]
            if listex.has_key(y):
                return self.liste[x][y]
            else:
                return None
        else:
            return None
    
    def getVoisins(self,hex,noeud):
        '''
        Récupère les deux hexagones voisins de hex
        '''
        if noeud == 0:
            #en haut à gauche:
            if hex.x % 2 == 0:
                if hex.y  > 0:
                    hex1 = self.getHexagone(hex.x-1,hex.y)
                else:
                    hex1 = self.getHexagone(hex.x-1,hex.y-1)
            else:
                if hex.y  > 0:
                    hex1 = self.getHexagone(hex.x-1,hex.y-1)
                else:
                    hex1 = self.getHexagone(hex.x-1,hex.y) 
            if hex.x % 2 == 0:
                hex2 = self.getHexagone(hex.x,hex.y-1)
            else:
                if hex.y==1:
                    hex2 = self.getHexagone(hex.x,hex.y-2)
                else:
                    hex2 = self.getHexagone(hex.x,hex.y-1)
        elif noeud == 1:
            #en haut à droite:
            #x-1, si y>0 y=y si y<=0 y=y-1
            if hex.x % 2 == 0:
                if hex.y  > 0:
                    hex1 = self.getHexagone(hex.x+1,hex.y)
                else:
                    hex1 = self.getHexagone(hex.x+1,hex.y-1)
            else:
                if hex.y  > 0:
                    hex1 = self.getHexagone(hex.x+1,hex.y-1)
                else:
                    hex1 = self.getHexagone(hex.x+1,hex.y) 
            #si x impair et y=1,-1 y-2 sinon y=-1
            if hex.x % 2 == 0:
                hex2 = self.getHexagone(hex.x,hex.y-1)
            else:
                if hex.y==1:
                    hex2 = self.getHexagone(hex.x,hex.y-2)
                else:
                    hex2 = self.getHexagone(hex.x,hex.y-1)
        elif noeud == 2:
            if hex.x % 2 == 0:
                if hex.y > 0:
                    hex1 = self.getHexagone(hex.x+1,hex.y)
                else:
                    hex1 = self.getHexagone(hex.x+1,hex.y-1)
            else:
                if hex.y <0:
                    hex1 = self.getHexagone(hex.x+1,hex.y)
                else:
                    hex1 = self.getHexagone(hex.x+1,hex.y-1)
             
            if hex.x % 2 == 0:
                if hex.y < 0:
                    hex2 = self.getHexagone(hex.x+1,hex.y)
                else:
                    hex2 = self.getHexagone(hex.x+1,hex.y+1)
            else:
                if hex.y >0:
                    hex2 = self.getHexagone(hex.x+1,hex.y)
                else:
                    hex2 = self.getHexagone(hex.x+1,hex.y+1)
        elif noeud == 5:
            if hex.x % 2 == 0:
                if hex.y < 0:
                    hex1 = self.getHexagone(hex.x-1,hex.y)
                else:
                    hex1 = self.getHexagone(hex.x-1,hex.y+1)
            else:
                if hex.y >0:
                    hex1 = self.getHexagone(hex.x-1,hex.y)
                else:
                    hex1 = self.getHexagone(hex.x-1,hex.y+1)
             
            if hex.x % 2 == 0:
                if hex.y > 0:
                    hex2 = self.getHexagone(hex.x-1,hex.y)
                else:
                    hex2 = self.getHexagone(hex.x-1,hex.y-1)
            else:
                if hex.y <0:
                    hex2 = self.getHexagone(hex.x-1,hex.y)
                else:
                    hex2 = self.getHexagone(hex.x-1,hex.y-1)
        elif noeud == 3:
            #en bas à droite:
            if hex.x % 2 == 0:
                if hex.y  < 0:
                    hex1 = self.getHexagone(hex.x+1,hex.y)
                else:
                    hex1 = self.getHexagone(hex.x+1,hex.y+1)
            else:
                if hex.y  < 0:
                    hex1 = self.getHexagone(hex.x+1,hex.y+1)
                else:
                    hex1 = self.getHexagone(hex.x+1,hex.y) 
            if hex.x % 2 == 0:
                hex2 = self.getHexagone(hex.x,hex.y+1)
            else:
                if hex.y==-1:
                    hex2 = self.getHexagone(hex.x,hex.y+2)
                else:
                    hex2 = self.getHexagone(hex.x,hex.y+1)
        elif noeud == 4:
            #en bas à gauche:
            if hex.x % 2 == 0:
                if hex.y  < 0:
                    hex1 = self.getHexagone(hex.x-1,hex.y)
                else:
                    hex1 = self.getHexagone(hex.x-1,hex.y+1)
            else:
                if hex.y  < 0:
                    hex1 = self.getHexagone(hex.x-1,hex.y+1)
                else:
                    hex1 = self.getHexagone(hex.x-1,hex.y) 
            #si x impair et y=1,-1 y-2 sinon y=-1
            if hex.x % 2 == 0:
                hex2 = self.getHexagone(hex.x,hex.y+1)
            else:
                if hex.y==-1:
                    hex2 = self.getHexagone(hex.x,hex.y+2)
                else:
                    hex2 = self.getHexagone(hex.x,hex.y+1)
        return [hex1,hex2]

class Plateau(object):
    '''
    Gère le plateau de jeu (dessin notamment)
    '''
    WIDTH, HEIGHT = 800, 1000
    HEXA_RAYON_X = 70
    HEXA_RAYON_Y = 70
    
    DESERT_COLOR = [0,0,0] #rgb
    BOIS_COLOR = [0.25,0.6,0]
    BLE_COLOR = [1,1,0]
    ARGILE_COLOR = [1,0,0]
    MINERAI_COLOR = [0.35,0.4,0.33]
    MOUTON_COLOR = [0.59,0.71,0,75]
    MER_COLOR = [0.08,0.34,0.75]
    
    def __init__(self):
        # Setup Cairo
        self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, Plateau.WIDTH, Plateau.HEIGHT)
        self.ctx = cairo.Context(self.surface)
        self.ctx.set_line_width(1)
        
    def creerPlateau(self,listeHexagone):
        for ligne,listeColonne in listeHexagone.liste.iteritems():
            for colonne,hex in listeColonne.iteritems():
                self.dessineHexagone(hex)

    def creerDonnees(self,listeHexagone):
        for ligne,listeColonne in listeHexagone.liste.iteritems():
            for colonne,hex in listeColonne.iteritems():
                self.ecritDonnees(hex)

    def dessineHexagone(self,hex):
        '''dessine un hexagone'''
        x = hex.x
        y = hex.y
        type = hex.matiere
        valeur = hex.valeur
        #Coordonnées absolue du centre de l'hexagone à partir des coordonnées relatives sur la grille 
        x_relatif = Plateau.WIDTH/2 + 1.5*x*Plateau.HEXA_RAYON_X
        if x % 2 == 0:
            y_relatif = Plateau.HEIGHT/2 + 2*y*Plateau.HEXA_RAYON_Y
        else:
            if y > 0:
                y_relatif = Plateau.HEIGHT/2 + (2*y-1)*Plateau.HEXA_RAYON_Y      
            else:
                y_relatif = Plateau.HEIGHT/2 + (2*y+1)*Plateau.HEXA_RAYON_Y
        valeursX = [ x_relatif-Plateau.HEXA_RAYON_X/2,	x_relatif+Plateau.HEXA_RAYON_X/2,	x_relatif+Plateau.HEXA_RAYON_X,	x_relatif+Plateau.HEXA_RAYON_X/2,	x_relatif-Plateau.HEXA_RAYON_X/2,	x_relatif-Plateau.HEXA_RAYON_X ]
        valeursY = [ y_relatif-Plateau.HEXA_RAYON_Y,	y_relatif-Plateau.HEXA_RAYON_Y,	y_relatif,	y_relatif+Plateau.HEXA_RAYON_Y,	y_relatif+Plateau.HEXA_RAYON_Y,	y_relatif	]
        #Traçage de l'hexagone
        self.ctx.move_to(valeursX[0], valeursY[0])
        for i in range(1,6):
            self.ctx.line_to(valeursX[i], valeursY[i])
        self.ctx.line_to(valeursX[0], valeursY[0])
        self.ctx.close_path()
        if type == Hexagone.ARGILE_TXT:
             couleur = Plateau.ARGILE_COLOR
        elif type == Hexagone.BOIS_TXT:
             couleur = Plateau.BOIS_COLOR
        elif type == Hexagone.BLE_TXT:
             couleur = Plateau.BLE_COLOR
        elif type == Hexagone.MINERAI_TXT:
             couleur = Plateau.MINERAI_COLOR
        elif type == Hexagone.MOUTON_TXT:
            couleur = Plateau.MOUTON_COLOR
        elif type == Hexagone.DESERT_TXT:
            couleur = Plateau.DESERT_COLOR
        else:
            couleur = Plateau.MER_COLOR
        self.ctx.set_source_rgb(couleur[0], couleur[1], couleur[2])
        self.ctx.fill_preserve()
        self.ctx.set_source_rgb(0,0,0)
        self.ctx.stroke()

    def ecritDonnees(self,hex):
        x = hex.x
        y = hex.y
        type = hex.matiere
        valeur = hex.valeur
        #Coordonnées absolue du centre de l'hexagone à partir des coordonnées relatives sur la grille 
        x_relatif = Plateau.WIDTH/2 + 1.5*x*Plateau.HEXA_RAYON_X
        if x % 2 == 0:
            y_relatif = Plateau.HEIGHT/2 + 2*y*Plateau.HEXA_RAYON_Y
        else:
            if y > 0:
                y_relatif = Plateau.HEIGHT/2 + (2*y-1)*Plateau.HEXA_RAYON_Y      
            else:
                y_relatif = Plateau.HEIGHT/2 + (2*y+1)*Plateau.HEXA_RAYON_Y
        valeursX = [ x_relatif-Plateau.HEXA_RAYON_X/2,	x_relatif+Plateau.HEXA_RAYON_X/2,	x_relatif+Plateau.HEXA_RAYON_X,	x_relatif+Plateau.HEXA_RAYON_X/2,	x_relatif-Plateau.HEXA_RAYON_X/2,	x_relatif-Plateau.HEXA_RAYON_X ]
        valeursY = [ y_relatif-Plateau.HEXA_RAYON_Y,	y_relatif-Plateau.HEXA_RAYON_Y,	y_relatif,	y_relatif+Plateau.HEXA_RAYON_Y,	y_relatif+Plateau.HEXA_RAYON_Y,	y_relatif	]

        #texte valeur dé
        if type != Hexagone.MER_TXT:
            valeurTXT = "%d"%valeur
            self.ctx.set_source_rgb(0, 0, 0)
            self.ctx.select_font_face("Georgia",cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
            self.ctx.set_font_size(26)
            x_bearing, y_bearing, width, height = self.ctx.text_extents(valeurTXT)[:4]
            self.ctx.move_to(x_relatif -(width/2 + x_bearing),y_relatif - (height/2 + y_bearing))
            self.ctx.show_text(valeurTXT)

            #texte proba
            for i in range(0,6):
                self.dessineRectangle(x0=valeursX[i]-15,y0=valeursY[i]-15,degradeCouleur=hex.noeuds[i]/31.0)
                valeurPROBA = "%d" % hex.noeuds[i]
                self.ctx.set_source_rgb(0, 0, 0)
                self.ctx.select_font_face("Arial",cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
                self.ctx.set_font_size(16)
                x_bearing, y_bearing, width, height = self.ctx.text_extents(valeurPROBA)[:4]
                self.ctx.move_to(valeursX[i]-(width/2 + x_bearing),valeursY[i]- (height/2 + y_bearing))
                self.ctx.show_text(valeurPROBA)
	    

    def dessineRectangle(self,x0,y0,rectWidth=30,rectHeight=30,degradeCouleur=1.0):
        radius = 10
        
        x1=x0+rectWidth
        y1=y0+rectHeight
        
        if rectWidth/2<radius:
            if rectHeight/2<radius:
                    self.ctx.move_to  (x0, (y0 + y1)/2)
                    self.ctx.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
                    self.ctx.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
                    self.ctx.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
                    self.ctx.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
            else:
                    self.ctx.move_to  (x0, y0 + radius)
                    self.ctx.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
                    self.ctx.curve_to (x1, y0, x1, y0, x1, y0 + radius)
                    self.ctx.line_to (x1 , y1 - radius)
                    self.ctx.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
                    self.ctx.curve_to (x0, y1, x0, y1, x0, y1- radius)
        else:
            if rectHeight/2<radius:
                    self.ctx.move_to  (x0, (y0 + y1)/2)
                    self.ctx.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
                    self.ctx.line_to (x1 - radius, y0)
                    self.ctx.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
                    self.ctx.curve_to (x1, y1, x1, y1, x1 - radius, y1)
                    self.ctx.line_to (x0 + radius, y1)
                    self.ctx.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
            else:
                    self.ctx.move_to  (x0, y0 + radius)
                    self.ctx.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
                    self.ctx.line_to (x1 - radius, y0)
                    self.ctx.curve_to (x1, y0, x1, y0, x1, y0 + radius)
                    self.ctx.line_to (x1 , y1 - radius)
                    self.ctx.curve_to (x1, y1, x1, y1, x1 - radius, y1)
                    self.ctx.line_to (x0 + radius, y1)
                    self.ctx.curve_to (x0, y1, x0, y1, x0, y1- radius)

        self.ctx.close_path ()
        self.ctx.set_source_rgb (0.605, 0.605*degradeCouleur, 1)
        self.ctx.fill_preserve ()
        self.ctx.set_source_rgba (0.5, 0, 0, 0.5)
        self.ctx.set_line_width (3.0)
        self.ctx.stroke ()
	
    def creerPNG(self,fichier):
        # Output a PNG file
        self.surface.write_to_png(fichier)

#Début script
#Création structure de donnée
listeHexagoneTriee = ListeHexagone()
try:
    file = open("testColons","rU").readlines()
    for line in file:
        #séparer coordonnées et données
        coordon=line.split('=')
        x,y=int(coordon[0].split(",")[0]),int(coordon[0].split(",")[1]) #récupération coordonnées
        matiere,valeur=coordon[1].split(",")[0],int(coordon[1].split(",")[1])
        hex = Hexagone(x,y,matiere,valeur)
        listeHexagoneTriee.ajouteHexagone(hex)
except:
    print "le fichier testColons n'existe pas ou est incorrect"
    sys.exit(-1)
    
listeHexagoneTriee.calculerProbaNoeud()

#partie graphique
plateauJeu = Plateau()
plateauJeu.creerPlateau(listeHexagoneTriee)
plateauJeu.creerDonnees(listeHexagoneTriee)
plateauJeu.creerPNG("hexagones.png")

